home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Medal Software 3
/
Gold Medal Software - Volume 3 (Gold Medal) (1994).iso
/
os2
/
pmics091.arj
/
PMICS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-05-30
|
74KB
|
2,222 lines
/*
PMICS -- PM interface for playing chess on internet chess server
Copyright (C) 1993 Kevin Nomura
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Author can be reached at email: chow@netcom.com
*/
/*****************************************************************************
This is version 0.91 (beta) of PMICS.
bugs:
- background fill pattern not filling whole window
- occasional transposition of data seen in terminal window during
challenge, but apparently no lost data
version 1.0 work items:
- full modem parameters (com port, baud, num bits, parity, colours)
- check mark on menu for lock/unlock
- clock timer should be keyed to absolute time
- resizability
- make match request dialog "modeless"
next release work items:
- gnuchess interface -- play locally or connect it to ICS
- rexx port?
- big board for 1024x768 displays
- modem redial on BUSY
- bughouse mode? (need ICS support)
5/7 add pattern to background fill GpiSetPattern,GpiQueryPS
use static controls for status window texts
5/8 option for I/O through session DosDupHandle,DosCreatePipe
5/9 lock/unlock (local echo of board moves)
5/13 detect what colour I am
scrollable/refreshable text using ListBox
5/14 found lost data bug: WinPostMsg failed
incremental board update
5/18 dialog box for match requests
5/19 fix update bug; gnuchess format for moves
5/28 color options; SCORE_FILE
icc /Sa /Ti- /Si /q /c /G4 /O- /Tdp /Fi /Gm pmics.c bitmaps.c
link386 pmics.obj+bitmaps.obj /m /noi /st:20000 /nol /pm:pm
******************************************************************************/
#define INCL_WIN
#define INCL_GPI
#define INCL_GPIPRIMITIVES
#define INCL_DOSPROCESS
#define INCL_DOSFILEMGR
#define INCL_DOSDEVIOCTL
#define INCL_DOSDEVICES
#define INCL_DOSDATETIME
#define INCL_DOSQUEUES
#define INCL_DOSEXCEPTIONS
#include <os2.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include "pmics.h"
#define LOG_FILE "pmics.log" // debug log
#define SCORE_FILE "pmics.sco" // game scores
#define LBX 1
#define LBY 1
/* frame window parameters */
#define APP_TITLE "PMICS - Internet Chess Server"
#define WCP_MAIN "WCP_MAIN"
int FW_X, FW_Y;
int CW_X, CW_Y;
/* board window parameters */
#define WCP_BOARD "WCP_BOARD"
#define BW_X (SQUARESIZE*8)
#define BW_Y BW_X
#define FW_BW_X 0
#define FW_BW_Y (CW_Y - BW_Y) // upper left
/* message window parameters */
#define WCP_MSG "WCP_MSG"
#define MW_X CW_X
#define MW_Y (CW_Y - BW_Y)
#define FW_MW_X 0 // lower left
#define FW_MW_Y 0
#define TERM_SAVED_LINES 200
/* stats window parameters */
#define WCP_STAT "WCP_STAT"
#define SW_X 260
#define SW_Y BW_Y
#define FW_SW_X (BW_X+8)
#define FW_SW_Y FW_BW_Y
// session stuff
PID ChildPID = 0;
#define HF_STDIN 0
#define HF_STDOUT 1
#define PIPESIZE 1024
void (*CommSpeak)(char *s);
class GAME
{
private:
char state; // 0=invalid, 1=valid
public:
char piece[8][8];
char opiece[8][8]; // from previous refresh, for incremental update
int moveNum, prevMoveNum;
int gameNum;
char playerW[17], playerB[17], opponent[17];
char onMove, prevOnMove;
int timeW, timeB, lastMoveTime;
char atTop; /* 'B' or 'W' */
char oAtTop;
char clockRun;
char lastMove[8]; // o-o shortest, P/a2-a4 longest
GAME() {state = 0;}
char is_valid() {return (state != 0);}
void init();
void plot(HPS hps);
void update(HPS hps);
void move(HPS hps, char rankFrom, char fileFrom, char rankTo, char fileTo);
void orient(char colour); // ' ' toggles
void plot_piece(HPS hps, char piece, char rank, char file);
void msg_style_8(char *s);
int IsInitialPosition() {return (moveNum == 1) && (onMove == 'W');}
} board;
struct
{
char BoardSize;
char CommMode;
char ComPort;
ULONG ComBaud;
ULONG WinX, WinY; // user-specified window dimensions
char DialString[128];
char *wsc, *bsc, *wpc, *bpc; // colour specs for squares, pieces
char *fcp; // program executed in session mode
} profile;
typedef struct
{
char RatedMode[8], BlitzMode[9], OppName[17];
char OppRating[11];
int TimeMin, TimeSec;
} MATCHPARMS;
typedef enum
{
PI_EMPTY = 0,
PI_B_ROO, PI_B_KNI, PI_B_BIS, PI_B_QUE, PI_B_KIN, PI_B_PAW,
PI_W_ROO, PI_W_KNI, PI_W_BIS, PI_W_QUE, PI_W_KIN, PI_W_PAW
};
#define is_black(p) ((p)>=PI_B_ROO && (p)<=PI_B_PAW)
#define is_white(p) ((p)>=PI_W_ROO && (p)<=PI_W_PAW)
#define BITS_BYTES (SQUARESIZE*SQUARESIZE/8)
class TXQ
{
private:
enum {queuel=12, queuec=255, winl=9};
char buf[queuel][queuec];
int headl, headc;
int taill, tailc;
public:
TXQ();
void CharIn(char c);
char *FinishLine();
char *CurLine();
char *WinLine(int n);
char *BufLine(int n);
void Dump();
} txq;
char *pi_bits[13]; // bitmap pointers
HAB hab; // anchor block
FILE *logfile; // debug log
FILE *scorefile; // game scores
HFILE hcom; // com port
int SQUARESIZE;
DATETIME keyDt;
int txti = 0;
char lastAction[64] = ""; // mouse button 2 action
HWND hTerm = NULLHANDLE;
HWND hFrame = NULLHANDLE;
HWND hClient = NULLHANDLE;
HWND hBoard = NULLHANDLE;
HWND hStat = NULLHANDLE;
typedef struct _timel_parm
{
HWND hwnd;
int ms;
} timel_parm;
/*********************************/
/* Internal function prototypes */
/*********************************/
static VOID _System timel(timel_parm *tp);
static VOID _System TxComIn(ULONG dummy);
/* message parsers */
static void ProcessChallenge(HWND hwnd, char *s);
static void setup(int i);
static void TermPut(HWND hwnd, HPS hps, char *s);
static char ComInit();
static int SessionInit();
#define IN(a,low,high) ((a)>=(low) && (a)<=(high))
#define at(hwnd,a,b) {POINTL p; p.x=(a); p.y=(b); GpiMove(hwnd,&p);}
/*****************************************************************************/
MRESULT EXPENTRY FrameProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
static HPS hps; /* presentation space handle */
static HDC hdc;
switch( msg )
{
case WM_CREATE:
return (MRESULT) FALSE;
case WM_PAINT:
{
RECTL rect;
HRGN hrgn;
SIZEL sizel;
hps = WinBeginPaint ( hwnd , 0L , &rect );
GpiSetPattern(hps, PATSYM_DENSE6);
GpiQueryPS(hps, &sizel);
rect.xLeft = 0;
rect.yBottom = 0;
rect.xRight = sizel.cx;
rect.yTop = sizel.cy;
GpiSetColor(hps, CLR_WHITE);
GpiSetBackColor(hps, CLR_BLUE);
hrgn = GpiCreateRegion(hps, 1, &rect);
GpiPaintRegion(hps, hrgn);
GpiDestroyRegion(hps, hrgn);
/* WinFillRect (hps, &rect, CLR_BLUE);*/
WinEndPaint (hps);
return (MRESULT) NULL;
}
case WM_CLOSE:
WinPostMsg( hwnd, WM_QUIT, 0L, 0L );
// clean up child processes
if (ChildPID != 0)
{
RESULTCODES res;
PID pid;
/* if (DosKillProcess (DKP_PROCESSTREE, ChildPID) == 0)
DosWaitChild(DCWA_PROCESSTREE, DCWW_WAIT, &res, &pid, ChildPID);
Naturally this hung the system the first time I tried it. sheesh */
DosKillProcess (DKP_PROCESS, ChildPID); // just blow it away
}
return (MRESULT) NULL;
case WM_CHAR:
{
/* pass keypress to children (Term, in particular) */
/* WinBroadcastMsg(hwnd, msg, mp1, mp2, BMSG_POST);*/
WinPostMsg(hTerm, msg, mp1, mp2);
return (MRESULT)TRUE;
}
case WM_COMMAND:
switch (SHORT1FROMMP(mp1))
{
case IDM_DIAL:
(*CommSpeak)("ATDT2419796\015");
return (MRESULT) NULL;
case IDM_SERVER_LOGIN:
(*CommSpeak)("telnet aragorn.andrew.cmu.edu 5000\n");
return (MRESULT) NULL;
case IDM_CAPTURE:
{
FONTDLG fnt;
char s[256];
int i;
for (i=1; i<=99; i++)
{
sprintf(s, "ch %d\n", i);
(*CommSpeak)(s);
}
memset(&fnt,0,sizeof(FONTDLG));
hps = WinGetPS(hwnd);
fnt.cbSize = sizeof(FONTDLG);
fnt.hpsScreen = hps;
fnt.pszFamilyname = (UCHAR *)s;
fnt.usFamilyBufLen = sizeof(s);
WinFontDlg(HWND_DESKTOP,hwnd,&fnt);
WinReleasePS(hps);
return (MRESULT) NULL;
}
case IDM_FLIP:
board.orient(' '); // toggle it
WinInvalidateRegion(hBoard, NULLHANDLE, 0);
WinSendMsg(hStat, IDM_STAT, 0L, 0L); // player names change
return (MRESULT) NULL;
case IDM_ICSCMD_REFRESH:
{
char s[32];
if (board.is_valid())
sprintf(s,"\nrefresh %d\n", board.gameNum);
else
sprintf(s,"\nrefresh\n");
(*CommSpeak)(s);
return (MRESULT)NULL;
}
case IDM_ICSCMD_FLAG:
(*CommSpeak)("\nflag\n");
strcpy(lastAction,"flag\n");
return (MRESULT)NULL;
case IDM_SMALL:
setup(1);
return (MRESULT)NULL;
case IDM_MEDIUM:
setup(2);
return (MRESULT)NULL;
case IDM_LARGE:
setup(3);
return (MRESULT)NULL;
case IDM_NEWBOARD:
board.init();
WinInvalidateRegion(hBoard, NULLHANDLE, 0);
return (MRESULT)NULL;
case IDM_BOARD_REPLOT:
WinInvalidateRegion(hBoard, NULLHANDLE, 0);
return (MRESULT)NULL;
case IDM_BOARD_LOCK:
case IDM_BOARD_UNLOCK:
WinPostMsg(hBoard, SHORT1FROMMP(mp1), 0L, 0L);
if (ChildPID != 0) DosSendSignalException(ChildPID, XCPT_SIGNAL_INTR);
return (MRESULT)NULL;
case IDM_TXQ_DUMP:
txq.Dump();
return (MRESULT)NULL;
case IDM_TEST_CHALLENGE:
ProcessChallenge(hwnd, "Unrated blitz match 7 7 requested with abyss. (unreg.)");
return (MRESULT)NULL;
case IDM_QUIT:
WinPostMsg( hwnd, WM_CLOSE, 0L, 0L );
return (MRESULT) NULL;
}
default:
return ( WinDefWindowProc( hwnd, msg, mp1, mp2 ) );
}
}
LONG parse_colour(char *clrspec, LONG *default_colours)
{
LONG colour_value;
if (strcmp(clrspec, "blue")==0) return default_colours[CLR_BLUE];
if (strcmp(clrspec, "red")==0) return default_colours[CLR_RED];
if (strcmp(clrspec, "pink")==0) return default_colours[CLR_PINK];
if (strcmp(clrspec, "green")==0) return default_colours[CLR_GREEN];
if (strcmp(clrspec, "cyan")==0) return default_colours[CLR_CYAN];
if (strcmp(clrspec, "yellow")==0) return default_colours[CLR_YELLOW];
if (strcmp(clrspec, "neutral")==0) return default_colours[CLR_NEUTRAL];
if (strcmp(clrspec, "darkgray")==0) return default_colours[CLR_DARKGRAY];
if (strcmp(clrspec, "darkblue")==0) return default_colours[CLR_DARKBLUE];
if (strcmp(clrspec, "darkred")==0) return default_colours[CLR_DARKRED];
if (strcmp(clrspec, "darkpink")==0) return default_colours[CLR_DARKPINK];
if (strcmp(clrspec, "darkgreen")==0) return default_colours[CLR_DARKGREEN];
if (strcmp(clrspec, "darkcyan")==0) return default_colours[CLR_DARKCYAN];
if (strcmp(clrspec, "brown")==0) return default_colours[CLR_BROWN];
if (strcmp(clrspec, "palegray")==0) return default_colours[CLR_PALEGRAY];
if (sscanf(clrspec, "%x", &colour_value) == 1)
return colour_value;
return default_colours[CLR_BACKGROUND];
}
/*****************************************************************************/
/* BoardProc - window method for BOARD */
/* */
/* Manages mouse-driven piece movement, game status display, and server */
/* message actions */
/*****************************************************************************/
MRESULT EXPENTRY BoardProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
static HPS hps; /* presentation space handle */
static HDC hdc;
static TID tid1;
static char locked = 1;
static short fromRank, fromFile, toRank, toFile;
switch( msg )
{
case WM_CREATE:
{
SIZEL sizl = {0,0};
LONG alTable[16]; // rgb colour values
LONG clr_wpc, clr_bpc, clr_wsc, clr_bsc;
hdc = WinOpenWindowDC(hwnd);
hps = GpiCreatePS(hab, hdc, &sizl, PU_PELS | GPIT_MICRO |
GPIA_ASSOC | GPIF_DEFAULT);
GpiQueryLogColorTable(hps, 0L, 0L, 16L, alTable);
clr_wpc = parse_colour(profile.wpc, alTable);
clr_bpc = parse_colour(profile.bpc, alTable);
clr_wsc = parse_colour(profile.wsc, alTable);
clr_bsc = parse_colour(profile.bsc, alTable);
alTable[CLR_WHITE_PIECE] = clr_wpc;
alTable[CLR_BLACK_PIECE] = clr_bpc;
alTable[CLR_WHITE_SQUARE] = clr_wsc;
alTable[CLR_BLACK_SQUARE] = clr_bsc;
GpiCreateLogColorTable(hps, 0L, LCOLF_CONSECRGB, 0L, 16L, alTable);
board.init();
return (MRESULT) FALSE;
}
case WM_PAINT:
{
RECTL rcInvalid;
/* hps = WinBeginPaint (hwnd , 0L , &rcInvalid);*/
WinBeginPaint (hwnd, hps, &rcInvalid);
board.plot(hps);
WinEndPaint ( hps );
return (MRESULT) NULL;
}
case WM_CLOSE:
WinReleasePS(hps);
WinPostMsg( hwnd, WM_QUIT, 0L, 0L );
fprintf(logfile,"BOARD method: goodbye\n");
return (MRESULT) NULL;
case WM_BUTTON1DOWN:
{
fromFile = SHORT1FROMMP(mp1) / SQUARESIZE;
fromFile = (board.atTop=='B') ? fromFile : 7-fromFile;
fromRank = SHORT2FROMMP(mp1) / SQUARESIZE;
fromRank = (board.atTop=='B') ? fromRank : 7-fromRank;
fprintf(logfile,"board: button down at (%d,%d)\n", SHORT1FROMMP(mp1), SHORT2FROMMP(mp1));
return (MRESULT)FALSE;
}
case WM_BUTTON1UP:
{
/* translate raster (x,y) to chessboard square */
/* as a function of SQUARESIZE and board.atTop */
toFile = SHORT1FROMMP(mp1) / SQUARESIZE;
toFile = (board.atTop=='B') ? toFile : 7-toFile;
toRank = SHORT2FROMMP(mp1) / SQUARESIZE;
toRank = (board.atTop=='B') ? toRank : 7-toRank;
fprintf(logfile,"board: button up at (%d,%d)\n", SHORT1FROMMP(mp1), SHORT2FROMMP(mp1));
if (IN(toRank,0,7) && IN(toFile,0,7) &&
IN(fromRank,0,7) && IN(fromFile,0,7) &&
! (toRank==fromRank && toFile == fromFile) &&
board.piece[fromRank][fromFile] != PI_EMPTY)
{
char s[256];
char pc = board.piece[fromRank][fromFile];
fprintf(logfile,"locked = %d\n", locked);
if (!locked)
board.move(hps, fromRank, fromFile, toRank, toFile);
sprintf(s,"%c%d%c%d\n", fromFile+'a', fromRank+1,
toFile+'a', toRank+1);
if (pc == PI_W_KIN && strcmp(s,"e1g1\n")==0 ||
pc == PI_B_KIN && strcmp(s,"e8g8\n")==0)
strcpy(s,"o-o\n");
else if (pc == PI_W_KIN && strcmp(s,"e1c1\n")==0 ||
pc == PI_B_KIN && strcmp(s,"e8c8\n")==0)
strcpy(s,"o-o-o\n");
if (ChildPID != 0) DosSendSignalException(ChildPID, XCPT_SIGNAL_INTR);
(*CommSpeak)(s);
strcpy(lastAction, s);
fromRank = fromFile = toRank = toFile = 8; /* invalid */
}
return (MRESULT)FALSE;
}
case WM_BUTTON2UP:
{
(*CommSpeak)(lastAction);
return (MRESULT)FALSE;
}
case IDM_BOARD_UNLOCK:
locked = 0;
return (MRESULT)TRUE;
case IDM_BOARD_LOCK:
locked = 1;
return (MRESULT)TRUE;
case IDM_BOARD_UPDATE:
board.update(hps);
return (MRESULT) NULL;
default:
return ( WinDefWindowProc( hwnd, msg, mp1, mp2 ) );
}
}
/*****************************************************************************/
/* text window processor
* cursor position in the i/o window is characterized by (row,col) where
* row 0 is the topmost row in the window and col 0 is the leftmost char
*/
MRESULT EXPENTRY TermProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
static HPS hps; /* presentation space handle */
static HDC hdc;
static TID comInTid, timerTid;
static HWND hTerm;
static char is_new_line; // state for IDM_DATA
switch( msg )
{
case WM_CREATE:
{
ULONG ulParmLen = 4;
static timel_parm tp;
SIZEL sizl = {0,0};
FATTRS fat;
/* get presentation space */
hdc = WinOpenWindowDC(hwnd);
hps = GpiCreatePS(hab, hdc, &sizl, PU_PELS | GPIT_MICRO |
GPIA_ASSOC | GPIF_DEFAULT);
if (profile.CommMode==0)
{ // communicate through serial port
if (ComInit()) // nonzero = failed
{
WinSendMsg(hFrame, WM_CLOSE, 0L, 0L);
return (MRESULT)FALSE;
}
DosCreateThread(&comInTid, (PFNTHREAD)(&TxComIn),
(ULONG)hwnd, 0,4096);
}
else
{ // communicate through command session
SessionInit();
}
DosGetDateTime(&keyDt);
tp.hwnd = hwnd;
tp.ms = 1000;
DosCreateThread(&timerTid, (PFNTHREAD)(&timel), (ULONG)&tp, 0, 4096);
/* set font to Helvetica */
fat.usRecordLength = sizeof(FATTRS);
fat.fsSelection = 0;
fat.lMatch = 0L;
fat.idRegistry = 0;
fat.usCodePage = 850;
fat.lMaxBaselineExt = 16;
fat.lAveCharWidth = 9;
fat.fsType = 0;
fat.fsFontUse = FATTR_FONTUSE_NOMIX;
strcpy(fat.szFacename, "Helv");
GpiCreateLogFont(hps, (PSTR8)NULL, 1L, &fat);
GpiSetCharSet(hps, 1L);
hTerm = WinCreateWindow(hwnd, WC_LISTBOX, (PSZ)"",
WS_VISIBLE | LS_NOADJUSTPOS,
0, 0, MW_X, MW_Y,
hwnd,
HWND_TOP, 306, NULL, NULL);
is_new_line = 1; // initial state for text win
return (MRESULT)FALSE; /* IF YOU RETURN TRUE, BOOM */
}
case WM_CHAR:
{
char s[100], c;
USHORT fsflags = SHORT1FROMMP(mp1);
if (fsflags & KC_KEYUP)
return (MRESULT)FALSE;
if (c = CHAR1FROMMP(mp2))
{
fprintf(logfile,"term: char=%d %c\n", c, c);
if (fsflags & KC_CTRL)
{
if (c>='a' && c<='z')
c = c - 'a' + 1;
else
return (MRESULT)FALSE; /* bogus ctrl? */
}
s[0] = c;
s[1] = 0;
DosGetDateTime(&keyDt);
(*CommSpeak)(s);
}
/* if (c=='~')
WinSendMsg(hTerm, LM_DELETEALL, 0L, 0L);*/
// get out of the list box, restore normal focus
WinSetFocus(HWND_DESKTOP, hClient);
return (MRESULT)TRUE;
}
case IDM_COM_IN:
{
char c, *stat, *s2;
char *data = (char *)PVOIDFROMMP(mp1);
int i;
for (i=0; data[i]; i++)
{
c = data[i];
if (c != 10) // watch for EOL token
txq.CharIn(c);
else
{
s2 = txq.FinishLine();
if ((stat = strstr(s2, "#@#")) != (char *)NULL)
{ // status line
board.msg_style_8(stat);
}
else if ((stat = strstr(s2, "requested with")) != (char *)NULL)
{ // challenge
ProcessChallenge(hwnd, s2);
}
else if (strstr(s2, "has been checkmated") != (char *)NULL)
board.clockRun = FALSE;
else if (strstr(s2, "Your opponent has run out of time") != (char *)NULL)
board.clockRun = FALSE;
}
}
/***********************/
/* update text monitor */
/***********************/
for (char * p=data;;)
{
char c, *q, t[256], *tp;
USHORT n;
MPARAM mp;
if (is_new_line) // last plot ended cleanly, so insert new line
{
// find newline or EOS. build *t* filtering out crap.
for (q=p, tp=t; *q && *q!=10; q++)
{
if (*q == 13) ;
else if (*q == 8 && tp != t) tp--;
else *tp++ = *q;
}
*tp = 0; // terminate u
c = *q; // remember terminator from input
*q = 0;
n = WinInsertLboxItem(hTerm, MPFROMSHORT(LIT_END),MPFROMP(t));
WinQueryLboxItemText(hTerm, n-1, (PSZ)t, sizeof(t));
if (strncmp(t, "#@#", 3) == 0 && n>=2)
{
WinDeleteLboxItem(hTerm, n-1);
WinDeleteLboxItem(hTerm, n-2);
}
}
else // ended in mid-line, so append to last line
{
// load t with text of last item in terminal window
n = WinQueryLboxCount(hTerm) - 1;
WinQueryLboxItemText(hTerm, n, (PSZ)t, sizeof(t));
// newline or EOS terminates input, in different states
// q scans input data, tp is output position
for (q=p, tp=t+strlen(t); *q && *q!=10; q++)
{
if (*q == 13) ;
else if (*q == 8 && tp != t) tp--;
else *tp++ = *q;
}
*tp = 0; // terminate output
c = *q; // remember terminator from input
WinSetLboxItemText(hTerm, n, MPFROMP(t));
}
is_new_line = (c == 10);
if (c) // more data
p = q + 1;
else
break;
}
/* prune history buffer */
if (WinQueryLboxCount(hTerm) > TERM_SAVED_LINES)
{
while (WinDeleteLboxItem (hTerm, 0) > TERM_SAVED_LINES) ;
}
WinSendMsg(hTerm, LM_SETTOPINDEX,
MPFROMSHORT(WinQueryLboxCount(hTerm)), 0L);
free(data);
return (MRESULT)TRUE;
}
case IDM_TIMEL:
{
DATETIME dt;
int roughMins;
DosGetDateTime(&dt);
roughMins = (keyDt.minutes - dt.minutes);
roughMins = (roughMins >= 0) ? roughMins : -roughMins;
if (roughMins > 3)
{
fprintf(logfile,"keepalive: sending blank\n");
(*CommSpeak)(" ");
}
return (MRESULT)FALSE;
}
case WM_PAINT:
{
RECTL rcInvalid;
WinBeginPaint (hwnd , hps, &rcInvalid );
WinFillRect (hps, &rcInvalid, CLR_WHITE);
WinEndPaint (hps);
return (MRESULT) NULL;
}
case WM_CLOSE:
WinDestroyWindow(hTerm);
WinReleasePS(hps);
DosKillThread(comInTid);
DosKillThread(timerTid);
WinPostMsg( hwnd, WM_QUIT, 0L, 0L );
return (MRESULT) NULL;
default:
return ( WinDefWindowProc( hwnd, msg, mp1, mp2 ) );
}
}
/*****************************************************************************/
/* StatProc */
/*****************************************************************************/
/* */
/* Manages mouse-driven piece movement, game status display, and server */
/* message actions */
/*****************************************************************************/
MRESULT EXPENTRY StatProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
static HPS hps; /* presentation space handle */
static HDC hdc;
static TID tid1;
static HWND hMovelist, hGame, hBottom, hTop, hMove, hOnMove, hTest;
static HWND hBFlag, hBResign, hBRefresh, hBDraw;
const ULONG backgnd = CLR_DARKGRAY;
APIRET rc;
switch( msg )
{
case WM_CREATE:
{
SIZEL sizl = {0,0};
static timel_parm tp;
tp.hwnd = hwnd;
tp.ms = 1000;
/* rc = DosCreateThread(&tid1, (PFNTHREAD)(&timel), (ULONG)&tp, 0, 4096);*/
WinStartTimer(hab, hwnd, ID_PMICS_STAT, 1000);
hdc = WinOpenWindowDC(hwnd);
hps = GpiCreatePS(hab, hdc, &sizl, PU_PELS | GPIT_MICRO |
GPIA_ASSOC | GPIF_DEFAULT);
/* WinLoadDlg(hwnd, hwnd, ScoreProc, NULLHANDLE, 100, 0);*/
GpiSetColor(hps, CLR_BLACK);
GpiSetBackColor(hps, backgnd);
/* hTest = WinCreateWindow(hwnd, WC_STATIC, (PSZ)"",
WS_VISIBLE | SS_GROUPBOX | SS_FGNDRECT |
DT_LEFT | DT_VCENTER,
60, 280, 80, 40,
hwnd, HWND_TOP, 399, NULL, NULL);*/
hGame = WinCreateWindow(hwnd, WC_STATIC, (PSZ)"",
WS_VISIBLE | SS_TEXT | DT_LEFT | DT_VCENTER,
70, 290, 60, 20,
hwnd, HWND_TOP, 300, NULL, NULL);
/**************/
/* text boxes */
/**************/
hTop = WinCreateWindow(hwnd, WC_STATIC, (PSZ)"",
WS_VISIBLE | SS_TEXT | DT_LEFT | DT_VCENTER,
10, 250, 180, 20,
hwnd, HWND_TOP, 301, NULL, NULL);
hBottom = WinCreateWindow(hwnd, WC_STATIC, (PSZ)"",
WS_VISIBLE | SS_TEXT | DT_LEFT | DT_VCENTER,
10, 210, 180, 20,
hwnd, HWND_TOP, 302, NULL, NULL);
hMove = WinCreateWindow(hwnd, WC_STATIC, (PSZ)"",
WS_VISIBLE | SS_TEXT | DT_LEFT | DT_VCENTER,
10, 150, 120, 20,
hwnd, HWND_TOP, 303, NULL, NULL);
hOnMove = WinCreateWindow(hwnd, WC_STATIC, (PSZ)"",
WS_VISIBLE | SS_TEXT | DT_LEFT | DT_VCENTER,
10, 120, 120, 20,
hwnd, HWND_TOP, 304, NULL, NULL);
/***********/
/* buttons */
/***********/
hBFlag = WinCreateWindow(hwnd, WC_BUTTON, (PSZ)"flag",
WS_VISIBLE| BS_PUSHBUTTON| BS_NOPOINTERFOCUS,
200,290,50,25,
hwnd, HWND_TOP, IDM_ICSCMD_FLAG, NULL, NULL);
hBResign = WinCreateWindow(hwnd, WC_BUTTON, (PSZ)"resign",
WS_VISIBLE| BS_PUSHBUTTON| BS_NOPOINTERFOCUS,
200,250,50,25,
hwnd, HWND_TOP, IDM_ICSCMD_RESIGN, NULL, NULL);
hBRefresh = WinCreateWindow(hwnd, WC_BUTTON, (PSZ)"refresh",
WS_VISIBLE| BS_PUSHBUTTON| BS_NOPOINTERFOCUS,
200,210,50,25,
hwnd, HWND_TOP, IDM_ICSCMD_REFRESH, NULL, NULL);
hBDraw = WinCreateWindow(hwnd, WC_BUTTON, (PSZ)"draw",
WS_VISIBLE| BS_PUSHBUTTON| BS_NOPOINTERFOCUS,
200,170,50,25,
hwnd, HWND_TOP, IDM_ICSCMD_DRAW, NULL, NULL);
/* GpiSetColor(WinGetPS(hBResign), CLR_RED); no effect, sigh */
/***********/
/* moves */
/***********/
hMovelist = WinCreateWindow(hwnd, WC_LISTBOX, (PSZ)"",
WS_VISIBLE | LS_NOADJUSTPOS,
8, 20, SW_X-20, 85,
hwnd,
HWND_TOP, 305, NULL, NULL);
return (MRESULT) FALSE;
}
case WM_PAINT:
{
RECTL rcInvalid;
hps = WinBeginPaint (hwnd , 0L , &rcInvalid);
WinFillRect (hps, &rcInvalid, CLR_DARKGRAY);
WinEndPaint (hps);
return (MRESULT) NULL;
}
case WM_COMMAND:
{
switch(SHORT1FROMMP(mp1))
{
case IDM_ICSCMD_FLAG: /* flag */
(*CommSpeak)("flag\n");
break;
case IDM_ICSCMD_RESIGN:
(*CommSpeak)("resign\n");
break;
case IDM_ICSCMD_DRAW:
(*CommSpeak)("draw\n");
break;
case IDM_ICSCMD_REFRESH:
{
char s[32];
if (board.is_valid())
sprintf(s,"\nrefresh %d\n", board.gameNum);
else
sprintf(s,"\nrefresh\n");
(*CommSpeak)(s);
return (MRESULT)NULL;
}
}
}
case WM_TIMER:
case IDM_TIMEL:
{
char s[256];
hps = WinGetPS(hwnd);
GpiSetColor(hps, CLR_BLACK);
GpiSetBackColor(hps, CLR_DARKGRAY);
/*if ( ! board.clockRun)
return;*/
if (board.onMove != 'B') // update WHITE clock
{
--board.timeW;
sprintf(s,"%s %d:%02d", board.playerW, board.timeW/60, board.timeW%60);
GpiSetColor(hps, (board.onMove != 'B' ? CLR_BLUE : CLR_BLACK));
WinSetWindowText(board.atTop=='B' ? hBottom : hTop, (PSZ)s);
}
else // update BLACK clock
{
--board.timeB;
sprintf(s,"%s %d:%02d", board.playerB, board.timeB/60, board.timeB%60);
GpiSetColor(hps, (board.onMove == 'B' ? CLR_BLUE : CLR_BLACK));
WinSetWindowText(board.atTop=='B' ? hTop : hBottom, (PSZ)s);
}
WinReleasePS(hps);
return (MRESULT)0;
}
case IDM_STAT:
{
char s[256];
int n;
GpiSetColor(hps, CLR_BLACK);
GpiSetBackColor(hps, backgnd);
sprintf(s,"Game %d", board.gameNum);
WinSetWindowText(hGame, (PSZ)s);
WinSetWindowText(hTest, (PSZ)"Pmics");
sprintf(s,"%s %d:%02d", board.playerW, board.timeW/60, board.timeW%60);
/* GpiSetColor(hps, (board.onMove != 'B' ? CLR_BLUE : CLR_BLACK));*/
WinSetWindowText(board.atTop=='B' ? hBottom : hTop, (PSZ)s);
sprintf(s,"%s %d:%02d", board.playerB, board.timeB/60, board.timeB%60);
/* GpiSetColor(hps, (board.onMove == 'B' ? CLR_BLUE : CLR_BLACK));*/
WinSetWindowText(board.atTop=='B' ? hTop : hBottom, (PSZ)s);
sprintf(s,"%s", board.lastMove);
WinSetWindowText(hMove, (PSZ)s);
sprintf(s,"%s", board.onMove=='B'?"black to move":"white to move");
WinSetWindowText(hOnMove, (PSZ)s);
// update the move list box
// moveNum==1 && onMove=='W' indicates initial position, not a move
if (! board.IsInitialPosition() &&
(board.moveNum != board.prevMoveNum ||
board.onMove != board.prevOnMove))
{
board.prevMoveNum = board.moveNum;
board.prevOnMove = board.onMove;
n = WinQueryLboxCount(hMovelist);
if (board.onMove == 'W') // last move was black
{
char oldMove[32];
WinSendMsg(hMovelist, LM_QUERYITEMTEXT,
MPFROM2SHORT(n-1,sizeof(oldMove)), (PSZ)oldMove);
sprintf(s,"%s %s", oldMove, board.lastMove);
WinSendMsg(hMovelist, LM_SETITEMTEXT,MPFROMSHORT(n-1), MPFROMP(s));
fprintf(scorefile, "%s\n", board.lastMove);
}
else // last move was white
{
sprintf(s,"%d. %s", board.moveNum, board.lastMove);
WinSendMsg(hMovelist, LM_INSERTITEM,
MPFROMSHORT(LIT_END), MPFROMP(s));
fprintf(scorefile,"%d. %-8s ", board.moveNum, board.lastMove);
}
fprintf(logfile,"LIST: %d items\n", n);
}
{USHORT n = SHORT1FROMMP(WinSendMsg(hMovelist, LM_QUERYITEMCOUNT, 0L, 0L));
if (n>100)
while (SHORT1FROMMP(WinSendMsg(hMovelist, LM_DELETEITEM, 0L, 0L)) > 100) ;
n = SHORT1FROMMP(WinSendMsg(hMovelist, LM_QUERYITEMCOUNT, 0L, 0L));
WinPostMsg(hMovelist, LM_SETTOPINDEX, MPFROMLONG(n), 0L);
}
return (MRESULT) FALSE;
}
case WM_CHAR: // get out of the list box, restore normal focus
WinSetFocus(HWND_DESKTOP, hClient);
WinPostMsg(hTerm, msg, mp1, mp2);
return (MRESULT)TRUE;
case WM_CLOSE:
DosKillThread(tid1);
WinReleasePS(hps);
WinPostMsg( hwnd, WM_QUIT, 0L, 0L );
return (MRESULT) NULL;
default:
return ( WinDefWindowProc( hwnd, msg, mp1, mp2 ) );
}
}
MRESULT EXPENTRY ChallengeProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
USHORT us;
char s[64]; // workarea
switch(msg)
{
case WM_COMMAND:
{
MATCHPARMS *mat; // wont work for multiple instantiations
int min,sec;
switch(us=SHORT1FROMMP(mp1))
{
case ID_MATCH_ACCEPT:
mat = (MATCHPARMS *)WinQueryWindowPtr(hwnd, 0);
WinQueryDlgItemText(hwnd, ID_MATCH_TIME, sizeof(s)-1, (PSZ)s);
sscanf(s, "%d %d", &(mat->TimeMin), &(mat->TimeSec));
WinDismissDlg(hwnd, us);
break;
case ID_MATCH_DECLINE:
case ID_MATCH_IGNORE:
WinDismissDlg(hwnd, us);
break;
}
return (MRESULT)TRUE;
}
case WM_INITDLG:
{
MATCHPARMS *mat; // wont work for multiple instantiations
mat = (MATCHPARMS *)mp2;
WinSetWindowPtr(hwnd, 0, (PVOID)mat);
fprintf(logfile,"challengeproc: mp1=%x mp2=%x\n", (ULONG)mp1, (ULONG)mp2);
sprintf(s, "%s (%s)", mat->OppName, mat->OppRating);
WinSetDlgItemText(hwnd, ID_MATCH_TEXT1, (PSZ)s);
sprintf(s, "requests %s %s match", mat->RatedMode, mat->BlitzMode);
WinSetDlgItemText(hwnd, ID_MATCH_TEXT2, (PSZ)s);
sprintf(s, "%d %d", mat->TimeMin, mat->TimeSec);
WinSetDlgItemText(hwnd, ID_MATCH_TIME, (PSZ)s);
return (MRESULT)0;
}
default:
return WinDefDlgProc(hwnd, msg, mp1, mp2);
}
}
/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
/*************/
/* TermPut */
/*************/
#define LMARG 4
#define BMARG 4
static void TermPut(HWND hwnd, HPS hps, char *s)
{
static int currow=0, curcol=0;
static const int maxrow = 10;
static const int maxcol = 80;
static POINTL TermPos = {LMARG,BMARG};
GpiMove(hps, &TermPos);
for (; *s; s++)
{
RECTL rectl;
HRGN hrgn;
if (*s == 13) continue; /* linefeed -- bound to CR, so ignore */
if (*s == 10 || TermPos.x+8 > FW_X)
{
WinScrollWindow(hwnd, 0, (LONG)18, (PRECTL)NULL, (PRECTL)NULL,
(HRGN)NULLHANDLE, &rectl, 0);
GpiSetColor(hps, CLR_WHITE);
hrgn = GpiCreateRegion(hps, 1, &rectl);
GpiPaintRegion(hps, hrgn);
GpiDestroyRegion(hps, hrgn);
TermPos.x = LMARG;
GpiMove(hps, &TermPos);
if (*s == 10) continue; // linefeed is not plotted
}
GpiSetColor(hps, CLR_BLACK);
GpiCharString(hps,1,(PCH)s);
}
GpiQueryCurrentPosition(hps, &TermPos);
}
/*****************************************************************************/
/* TxComIn - thread to monitor COM port */
/*****************************************************************************/
/* thread does blocking reads against COM: and send data via window */
/* messages to the parent window as data arrives */
/*****************************************************************************/
static VOID TxComIn(ULONG dummy)
{
ULONG bytesRead;
APIRET rc;
BYTE *buf;
fprintf(logfile,"TxComIn thread: hello\n"); fflush(logfile);
WinInitialize(0);
while (1)
{
buf = (BYTE *)malloc(2049);
rc = DosRead(hcom, buf, 2048, &bytesRead);
if (bytesRead == 0) continue;
buf[bytesRead] = 0;
fprintf(logfile,"TxComIn: rc=%d bytes= %d buf=%s\n", rc, bytesRead, buf);
while (!WinPostMsg(hTerm, IDM_COM_IN, MPFROMP(buf), NULL))
{
fprintf(logfile,"ERROR: txcomin, winpostmsg; sleeping 250\n");
DosSleep(250); // let system catch its breath
}
}
}
/* do blocking reads against COM: and send data via windowing messages */
/* to the parent window as data arrives */
static VOID TxComOut(char *s)
{
ULONG cbWritten;
DosGetDateTime(&keyDt);
DosWrite(hcom, s, strlen(s), &cbWritten);
fprintf(logfile,"TxComOut: %s\n",s);
}
static VOID _System PipeListen(ULONG readPipe)
{
BYTE *buf;
ULONG cbRead;
fprintf(stderr, "listening to pipe %d\n", readPipe);
WinInitialize(0);
while(1)
{
buf = (BYTE *)malloc(PIPESIZE+1);
DosRead(readPipe, (PVOID)buf, PIPESIZE, &cbRead);
buf[cbRead] = 0;
fprintf(logfile,"PipeListen: cbRead %d buf %s\n", cbRead, buf);
while (!WinPostMsg(hTerm, IDM_COM_IN, MPFROMP(buf), NULL))
{
fprintf(logfile,"ERROR: txcomin, winpostmsg; sleeping 250\n");
DosSleep(250); // let system catch its breath
}
/* WinSendMsg(hTerm, IDM_COM_IN, MPFROMP(buf), NULL);*/
}
}
static ULONG writePipe; // set by SessionInit
static void PipeSpeak(char *s)
{
ULONG cbWritten, n;
DosGetDateTime(&keyDt);
for (n=0; n<strlen(s); n++)
if (s[n] == '\012')
{
DosWrite(writePipe, (PVOID)"\015", 1, &cbWritten);
DosWrite(writePipe, (PVOID)(s+n), 1, &cbWritten);
}
else if (s[n] == '\015')
{
DosWrite(writePipe, (PVOID)(s+n), 1, &cbWritten);
DosWrite(writePipe, (PVOID)"\012", 1, &cbWritten);
}
else
DosWrite(writePipe, (PVOID)(s+n), 1, &cbWritten);
/* DosWrite(writePipe, (PVOID)s, strlen(s), &cbWritten);*/
/* fprintf(logfile,"PipeSpeak: %d %d %s\n", writePipe, cbWritten,s);*/
}
static int SessionInit()
{
// DosExecPgm stuff
CHAR LoadError[CCHMAXPATH];
RESULTCODES ReturnCodes;
ULONG Pid;
// pipe games stuff
HFILE hfOSave = -1, hfONew = HF_STDOUT;
HFILE hfOR, hfOW;
HFILE hfISave = -1, hfINew = HF_STDIN;
HFILE hfIR, hfIW;
APIRET rc;
// misc
ULONG pidPipeListen;
// redirect stdout
DosDupHandle(HF_STDOUT, &hfOSave); // save stdout
DosCreatePipe(&hfOR, &hfOW, PIPESIZE); // pipe for redirecting stdout
DosDupHandle(hfOW, &hfONew); // change stdout to the pipe
// redirect stdin
DosDupHandle(HF_STDIN, &hfISave); // save stdin
DosCreatePipe(&hfIR, &hfIW, PIPESIZE); // pipe for redirecting stdin
DosDupHandle(hfIR, &hfINew); // switch stdin to the pipe
// kick off a program with the gimmicked file handles
rc = DosExecPgm(LoadError, // object name buffer
sizeof(LoadError), // length of object name buffer
EXEC_ASYNC, // async/trace flags
(PSZ)"", // argument string
(PSZ)0, // environment string
&ReturnCodes, // termination codes
(PSZ)profile.fcp); // child program
ChildPID = ReturnCodes.codeTerminate; // pull out PID of child
DosClose(hfOW); // voodoo stuff the manual says to do
DosClose(hfIR);
hfONew = HF_STDOUT;
DosDupHandle(hfOSave, &hfONew); // bring stdout back
hfINew = HF_STDIN;
DosDupHandle(hfISave, &hfINew); // bring stdin back
if (rc != 0)
return 1; // DosExecPgm failed
// initiate a task to Listen to the pipe
DosCreateThread(&pidPipeListen, (PFNTHREAD)&PipeListen, (ULONG)hfOR, 0,4096);
writePipe = hfIW;
CommSpeak = &PipeSpeak;
//PipeSpeak("echo NOTE: your keystrokes will not echo until you hit ENTER!\n");
// wait for the child to die
//DosWaitChild(DCWA_PROCESS, DCWW_WAIT, &ReturnCodes, &Pid,
// ReturnCodes.codeTerminate);
return 0; // show ok
}
/*************/
/* BoardPlot */
/*************/
void GAME::plot(HPS hps)
{
BITMAPINFO2 pbmi;
BITMAPINFO2 pbmi64;
HBITMAP hbm;
POINTL ptl[4] = {0,0,64,64,0,0,64,64};
POINTL ptl2[4] = {80,80};
POINTL p;
int rank, file;
pbmi.cbFix = 16;
pbmi.cx = 40;
pbmi.cy = 40;
pbmi.cPlanes = 1;
pbmi.cBitCount = 1;
pbmi64.cbFix = 16;
pbmi64.cx = 64;
pbmi64.cy = 64;
pbmi64.cPlanes = 1;
pbmi64.cBitCount = 1;
/* GpiDrawBits(hps, bishop64, &pbmi64, 4, ptl, ROP_SRCCOPY, 0);
hbm = GpiCreateBitmap(hps, (PBITMAPINFOHEADER2)&pbmi, CBM_INIT, (PBYTE)bishop40, &pbmi);
WinDrawBitmap(hps, hbm, NULL, ptl2, CLR_BLACK, CLR_WHITE, DBM_NORMAL);*/
for (rank=0; rank<8; rank++)
for (file=0; file<8; file++)
plot_piece(hps,piece[rank][file],rank,file);
}
void GAME::update(HPS hps)
{
register int rank, file;
/* incremental update: opiece represents what is on the screen; piece */
/* is the actual state of the board. make the screen look like piece */
/* and copy piece to opiece. all updates (flip, statusproc, etc). are */
/* made to piece. */
for (rank=0; rank<8; rank++)
for (file=0; file<8; file++)
if (piece[rank][file] != opiece[rank][file] ||
oAtTop != atTop)
plot_piece(hps, piece[rank][file],rank,file);
oAtTop = atTop;
}
void GAME::orient(char colour)
{
if (colour == ' ')
atTop = (atTop == 'B' ? 'W' : 'B');
else
atTop = colour;
}
/****************/
/* plot_piece */
/****************/
void GAME::plot_piece(HPS hps, char piece, char rank, char file)
{
POINTL p;
SIZEL sizl;
RECTL rect;
HRGN hrgn;
char rfile, rrank; /* relative to board.atTop */
static char bits_fixed = 0;
/*fprintf(logfile,"plot: bits_byts:%d %x %x %x %x %x %x %x %x %x %x %x %x\n",
BITS_BYTES, pi_bits[1], pi_bits[2], pi_bits[3], pi_bits[4],
pi_bits[5], pi_bits[6], pi_bits[7], pi_bits[8], pi_bits[9],
pi_bits[10], pi_bits[11], pi_bits[12]);
fflush(logfile);*/
if (!bits_fixed)
{
int i,j;
struct
{
int b7:1,b6:1,b5:1,b4:1,b3:1,b2:1,b1:1,b0:1;
} c1,c2;
bits_fixed = 1;
for (i=1; i<=6; i++)
for (j=0; j<BITS_BYTES; j++)
{
memcpy(&c1,pi_bits[i]+j,1);
c2.b7=c1.b0;
c2.b6=c1.b1;
c2.b5=c1.b2;
c2.b4=c1.b3;
c2.b3=c1.b4;
c2.b2=c1.b5;
c2.b1=c1.b6;
c2.b0=c1.b7;
memcpy(pi_bits[i]+j,&c2,1);
}
}
sizl.cx = sizl.cy = SQUARESIZE;
rfile = (board.atTop=='B') ? file : 7-file;
rrank = (board.atTop=='B') ? rank : 7-rank;
/* paint the square */
rect.xLeft = SQUARESIZE*rfile;
rect.yBottom = SQUARESIZE*rrank;
rect.xRight = rect.xLeft+SQUARESIZE;
rect.yTop = rect.yBottom+SQUARESIZE;
/* hrgn = GpiCreateRegion(hps, 1, &rect);
GpiSetColor(hps, (rfile+rrank)&1 ? CLR_WHITE_SQUARE : CLR_BLACK_SQUARE);
GpiPaintRegion(hps, hrgn);
GpiDestroyRegion(hps, hrgn);*/
// one call is simpler than 4 -- but what does the manual mean by
// this function must only be used in draw mode (DM_DRAW)??
WinFillRect(hps, &rect, (rfile+rrank)&1? CLR_WHITE_SQUARE: CLR_BLACK_SQUARE);
/* paint the piece */
if (piece != PI_EMPTY)
{
p.x = SQUARESIZE*rfile;
p.y = SQUARESIZE*(rrank+1);
GpiMove(hps, &p);
GpiSetColor(hps, is_black(piece) ? CLR_BLACK_PIECE : CLR_WHITE_PIECE);
/* set background color explicitly to fix (?) problem */
/* of pieces appearing on a white background. */
GpiSetBackColor(hps, (rfile+rrank)&1 ? CLR_WHITE_SQUARE : CLR_BLACK_SQUARE);
GpiImage(hps, 0L, &sizl, BITS_BYTES, (PBYTE)(pi_bits[piece]));
}
opiece[rank][file] = piece;
}
/*************/
/* BoardInit */
/*************/
void GAME::init()
{
static char ipos[8][8] =
{
PI_W_ROO,PI_W_KNI,PI_W_BIS,PI_W_QUE,PI_W_KIN,PI_W_BIS,PI_W_KNI,PI_W_ROO,
PI_W_PAW,PI_W_PAW,PI_W_PAW,PI_W_PAW,PI_W_PAW,PI_W_PAW,PI_W_PAW,PI_W_PAW,
PI_EMPTY,PI_EMPTY,PI_EMPTY,PI_EMPTY,PI_EMPTY,PI_EMPTY,PI_EMPTY,PI_EMPTY,
PI_EMPTY,PI_EMPTY,PI_EMPTY,PI_EMPTY,PI_EMPTY,PI_EMPTY,PI_EMPTY,PI_EMPTY,
PI_EMPTY,PI_EMPTY,PI_EMPTY,PI_EMPTY,PI_EMPTY,PI_EMPTY,PI_EMPTY,PI_EMPTY,
PI_EMPTY,PI_EMPTY,PI_EMPTY,PI_EMPTY,PI_EMPTY,PI_EMPTY,PI_EMPTY,PI_EMPTY,
PI_B_PAW,PI_B_PAW,PI_B_PAW,PI_B_PAW,PI_B_PAW,PI_B_PAW,PI_B_PAW,PI_B_PAW,
PI_B_ROO,PI_B_KNI,PI_B_BIS,PI_B_QUE,PI_B_KIN,PI_B_BIS,PI_B_KNI,PI_B_ROO
};
register int rank,file;
for (rank=0; rank<8; rank++)
for (file=0; file<8; file++)
{
piece[rank][file] = ipos[rank][file];
opiece[rank][file] = PI_EMPTY; // forces plot update
}
atTop = oAtTop = 'B';
strcpy(playerW, "White");
strcpy(playerB, "Black");
timeW = 3600;
timeB = 3600;
onMove = 'W';
clockRun = FALSE;
}
/*************/
/* BoardMove */
/*************/
void GAME::move(HPS hps,char rankFrom, char fileFrom, char rankTo, char fileTo)
{
register char temp; /* to handle error case of a1->a1, etc */
temp = piece[rankFrom][fileFrom];
piece[rankFrom][fileFrom] = PI_EMPTY;
piece[rankTo][fileTo] = temp;
plot_piece(hps, PI_EMPTY, rankFrom, fileFrom);
plot_piece(hps, piece[rankTo][fileTo], rankTo, fileTo);
}
/*********/
/* TIMEL */
/*********/
static VOID timel(timel_parm *tp)
{
WinInitialize(0);
fprintf(logfile,"timel: ms=%d hwnd=%x\n", tp->ms, tp->hwnd);
while (1)
{
DosSleep(tp->ms);
WinPostMsg(tp->hwnd, IDM_TIMEL, NULL, NULL);
}
}
void GAME::msg_style_8(char *s)
{
char *position, *s2;
int i, rank, file;
struct _statMap
{
char startTrigger[3];
char gameNum[3];
char playerW[16];
char delim1;
char playerB[16];
char delim2;
char position[64];
char moveNum[3];
char onMove;
char strW[2], strB[2];
char timeW[5], timeB[5];
char lastMoveAndTime[10]; // variable: o-o or Pa3-a4 followed by ' '
// (mm:ss), so min length is 10 and may be greater
} *statMap = (struct _statMap *)s;
int min,sec;
fprintf(logfile,"ProcessStatusMsg:%s\n", s);
/* check for garbled data. status line must be terminated and */
/* the fixed portion must be present (up to but not including lastMove) */
if ((s2 = strstr(s,"@#@")) == (char *)NULL || // must have terminator
s2 - s < sizeof(*statMap)-sizeof(statMap->lastMoveAndTime))
{
int gamenum;
char refMsg[32];
static int errCnt = 0;
fprintf(logfile, "ERROR: bad status line. ignore and request refresh.\n");
if (++errCnt > 10) return; // prevent loop in case our method is bad
sscanf(statMap->gameNum, "%3d", &gamenum); // needed if mult monitor
sprintf(refMsg, "\nrefresh %d\n", gamenum);
(*CommSpeak)(refMsg);
return;
}
sscanf(statMap->gameNum, "%3d", &gameNum);
sscanf(statMap->playerW, "%16s", &playerW);
sscanf(statMap->playerB, "%16s", &playerB);
position = statMap->position;
sscanf(statMap->moveNum, "%3d", &moveNum);
onMove = statMap->onMove;
sscanf(statMap->timeW, "%5d", &timeW);
sscanf(statMap->timeB, "%5d", &timeB);
sscanf(statMap->lastMoveAndTime, "%7s (%d:%d)", &lastMove, &min, &sec);
lastMoveTime = min*60+sec;
clockRun = TRUE;
if (lastMove[1] == '/') // strip that slash
strcpy(lastMove+1, lastMove+2);
if (IsInitialPosition()) // new game -- orient brd
{
time_t ltime;
char time_buffer[32];
board.prevMoveNum = 0;
board.orient(statMap->delim1 == '*' ? 'B' : 'W');
(*CommSpeak)("observe\n");
// make header in score file in "PGN" format
fprintf(scorefile, "\n\n[White \"%s\"]\n", playerW);
fprintf(scorefile, "[Black \"%s\"]\n", playerB);
time(<ime);
strftime(time_buffer, sizeof(time_buffer), "%Y.%m.%d",
localtime(<ime));
fprintf(scorefile, "[Date \"%s\"]\n\n", time_buffer);
}
for (i=0; i<64; i++)
{
file = i & 7;
rank = i >> 3;
switch(position[i])
{
case 'R':
piece[rank][file] = PI_W_ROO;
break;
case 'N':
piece[rank][file] = PI_W_KNI;
break;
case 'B':
piece[rank][file] = PI_W_BIS;
break;
case 'Q':
piece[rank][file] = PI_W_QUE;
break;
case 'K':
piece[rank][file] = PI_W_KIN;
break;
case 'P':
piece[rank][file] = PI_W_PAW;
break;
case 'r':
piece[rank][file] = PI_B_ROO;
break;
case 'n':
piece[rank][file] = PI_B_KNI;
break;
case 'b':
piece[rank][file] = PI_B_BIS;
break;
case 'q':
piece[rank][file] = PI_B_QUE;
break;
case 'k':
piece[rank][file] = PI_B_KIN;
break;
case 'p':
piece[rank][file] = PI_B_PAW;
break;
default:
piece[rank][file] = PI_EMPTY;
break;
}
}
state = 1; // board is valid now
WinSendMsg(hBoard, IDM_BOARD_UPDATE, 0L, 0L);
WinSendMsg(hStat, IDM_STAT, 0L, 0L);
/* WinInvalidateRegion(hBoard, NULLHANDLE, 0);*/
}
/* Unrated blitz match 2 12 requested with glen. (unreg.)
You may accept this with "accept glen", decline it with
"decline glen", or propose different parameters.
VCS % Creating unrated blitz match 2 12 with glen.
*/
static void ProcessChallenge(HWND hwnd, char *s)
{
char *begin;
MATCHPARMS mat;
int n, rating, n2;
char s2[100];
HWND hMatch;
if ((begin=strstr(s,"Unrated")) == (char *)NULL &&
(begin=strstr(s,"Rated")) == (char *)NULL)
return; // it parses not
n = sscanf(begin, "%7s %8s match %d %d requested with %16s (%d)",
mat.RatedMode,
mat.BlitzMode,
&mat.TimeMin, &mat.TimeSec,
mat.OppName,
&rating); /* rating: (unreg) or (%d) */
if (n<5) // it parses not
return;
else if (n<6) // rating not converted
strcpy(mat.OppRating, "UNR");
else
sprintf(mat.OppRating, "%d", rating);
mat.OppName[strlen(mat.OppName)-1] = '\0'; // strip trailing '.'
DosBeep(1380,100); /* hertz, milliseconds -- mon dieu a simple utility */
n2 = WinDlgBox(HWND_DESKTOP, hwnd, ChallengeProc, NULLHANDLE, ID_MATCH, (PVOID)&mat);
switch (n2)
{
case ID_MATCH_ACCEPT:
sprintf(s2, "\nobserve\nstyle 8\nmatch %s %d %d\n", mat.OppName, mat.TimeMin, mat.TimeSec);
(*CommSpeak)(s2);
break;
case ID_MATCH_DECLINE:
sprintf(s2, "\ndecline %s\n", mat.OppName);
(*CommSpeak)(s2);
break;
}
#ifdef OLD
sprintf(s2, "%s (%s) requests\n%s %s match at %d %d",
matchOppName,
matchOppRating,
matchRatedMode,
matchBlitzMode,
matchTimeMin,
matchTimeSec);
switch(WinMessageBox(HWND_DESKTOP, hwnd,
(PSZ)s2,
(PSZ)"Match request",0,
MB_MOVEABLE | MB_YESNOCANCEL | MB_QUERY | MB_DEFBUTTON1))
{
case MBID_YES:
sprintf(s2, "\nobserve\nstyle 8\nmatch %s %d %d\n", matchOppName, matchTimeMin, matchTimeSec);
(*CommSpeak)(s2);
break;
case MBID_NO:
sprintf(s2, "\ndecline %s\n", matchOppName);
(*CommSpeak)(s2);
break;
}
#endif
}
static void setup(int size)
{
extern char xs_s_r_bits[], xs_s_kt_bits[], xs_s_b_bits[], xs_s_q_bits[],
xs_s_p_bits[], xs_s_k_bits[],
solid_bishop_bits[], solid_knight_bits[], solid_pawn_bits[],
solid_queen_bits[], solid_rook_bits[], solid_king_bits[],
bishop_small_bits[], king_small_bits[], knight_small_bits[],
pawn_small_bits[], queen_small_bits[], rook_small_bits[];
switch(size)
{
case 1: /* small */
SQUARESIZE = 40;
pi_bits[0] = (char *)NULL;
pi_bits[1] = xs_s_r_bits;
pi_bits[2] = xs_s_kt_bits;
pi_bits[3] = xs_s_b_bits;
pi_bits[4] = xs_s_q_bits;
pi_bits[5] = xs_s_k_bits;
pi_bits[6] = xs_s_p_bits;
pi_bits[7] = xs_s_r_bits;
pi_bits[8] = xs_s_kt_bits;
pi_bits[9] = xs_s_b_bits;
pi_bits[10] = xs_s_q_bits;
pi_bits[11] = xs_s_k_bits;
pi_bits[12] = xs_s_p_bits;
break;
case 2: /* medium */
SQUARESIZE = 64;
pi_bits[0] = (char *)NULL;
pi_bits[1] = rook_small_bits;
pi_bits[2] = knight_small_bits;
pi_bits[3] = bishop_small_bits;
pi_bits[4] = queen_small_bits;
pi_bits[5] = king_small_bits;
pi_bits[6] = pawn_small_bits;
pi_bits[7] = rook_small_bits;
pi_bits[8] = knight_small_bits;
pi_bits[9] = bishop_small_bits;
pi_bits[10] = queen_small_bits;
pi_bits[11] = king_small_bits;
pi_bits[12] = pawn_small_bits;
break;
case 3: /* large */
SQUARESIZE = 80;
pi_bits[0] = (char *)NULL;
pi_bits[1] = solid_rook_bits;
pi_bits[2] = solid_knight_bits;
pi_bits[3] = solid_bishop_bits;
pi_bits[4] = solid_queen_bits;
pi_bits[5] = solid_king_bits;
pi_bits[6] = solid_pawn_bits;
pi_bits[7] = solid_rook_bits;
pi_bits[8] = solid_knight_bits;
pi_bits[9] = solid_bishop_bits;
pi_bits[10] = solid_queen_bits;
pi_bits[11] = solid_king_bits;
pi_bits[12] = solid_pawn_bits;
break;
}
}
/*****************/
/* CLASS TXQ */
/*****************/
TXQ::TXQ()
{
headl = headc = taill = tailc = 0; // empty queue
}
void TXQ::CharIn(char c)
{
if (c == 015) return; // discard CR, no one depends on it
if (tailc != queuec) // if line overflow, discard text
buf[taill][tailc++] = c;
else
fprintf(logfile,"TXQ: OVERFLOW\n");
}
char * TXQ::FinishLine()
{
char *p = buf[taill];
if (tailc == queuec) tailc--; // force in line terminator
buf[taill][tailc] = '\0';
fprintf(logfile,"finishline %d %s\n", tailc, p);
taill = (taill+1) % queuel;
tailc = 0;
if (taill == headl) // full queue -- discard oldest line
headl = (headl+1) % queuel;
return p;
}
char * TXQ::CurLine() // current line as is
{
buf[taill][(tailc==queuec) ? tailc-1 : tailc] = '\0';
return buf[taill];
}
char * TXQ::WinLine(int n) // line n relative to window of last winl lines
{
buf[taill][(tailc==queuec) ? tailc-1 : tailc] = '\0';
return buf[(taill+queuel-winl+n) % queuel];
}
char * TXQ::BufLine(int n) // line n relative to head (0=first)
{
char *p;
buf[taill][(tailc==queuec) ? tailc-1 : tailc] = '\0';
p = buf[(headl+n) % queuel]; // guaranteed within the queue, somewhere
return p;
}
void TXQ::Dump()
{
int i;
fprintf(logfile,"Text queue dump\n===============\n");
fprintf(logfile,"taill %d tailc %d headl %d headc %d\n",
taill, tailc, headl, headc);
for (i = headl; i != taill; i = (i+1) % queuel)
fprintf(logfile, "%02d: %s\n", i, buf[i]);
if (headl != taill) // that would be empty queue
{
buf[taill][(tailc==queuec) ? tailc-1 : tailc] = '\0';
fprintf(logfile, "taill: %s\n", buf[taill]);
}
}
#define COMOPEN(s) \
DosOpen((PSZ)(s), &hcom, &crap, 0, FILE_NORMAL, \
FILE_OPEN, OPEN_ACCESS_READWRITE | OPEN_FLAGS_FAIL_ON_ERROR | \
OPEN_SHARE_DENYREADWRITE, (PEAOP2) NULL)
static char ComInit()
{
APIRET rc;
DCBINFO dcbinfo; /* Device control block for Ioctl 53H, 73H */
LINECONTROL lnctlBuf;
ULONG ulParmLen;
ULONG crap;
char comfile[5];
int comnum;
/**********************************************************************/
/* Get File Handle hcom for COM port (shared read/write access) */
/* if /Cn was specified then use com port n. Otherwise try com ports */
/* 1-4 in turn and use the first one that opens succesfully. */
/**********************************************************************/
if (profile.ComPort != 0)
{
sprintf(comfile, "COM%1d", profile.ComPort);
rc = COMOPEN(comfile);
fprintf(logfile,"cominit: open %s rc=%d\n", comfile, rc);
if (rc)
{
WinMessageBox(HWND_DESKTOP, hClient,
(PSZ)"Unable to open specified COM port",
(PSZ)"Init failed", 0, MB_ICONEXCLAMATION | MB_OK);
return 1; // failed
}
}
else
{
for (comnum = 1; comnum <= 4; comnum++)
{
sprintf(comfile, "COM%1d", comnum);
rc = COMOPEN(comfile);
fprintf(logfile,"cominit: open %s rc=%d\n", comfile, rc);
if (rc == 0)
break;
}
if (rc)
{
WinMessageBox(HWND_DESKTOP, hClient,
(PSZ)"Unable to open any COM port. "
"Try specifying your COM port number with /Cn"
" and the baud rate with /Pnnn, e.g.\n"
" start pmics /c2 /p2400\n"
"to use COM2 at 2400 baud",
(PSZ)"Init failed", 0, MB_ICONEXCLAMATION | MB_OK);
return 1; // failed
}
}
#ifdef CRAP
/* Call Category 1 Function 42H Set Line Characteristics */
lnctlBuf.bDataBits = 8;
lnctlBuf.bParity = 0;
lnctlBuf.bStopBits = 1; /* IDD_ONESTOP = 20 */
ulParmLen = sizeof(LINECONTROL);
rc = DosDevIOCtl(hcom, IOCTL_ASYNC, ASYNC_SETLINECTRL, &lnctlBuf, sizeof(LINECONTROL), &ulParmLen, NULL, 0, (PULONG)NULL);
fprintf(logfile,"line characteristics rc=%d\n", rc); fflush(stdout);
#endif
/* Call Category 1 Function 73H Query Device Control Block */
ulParmLen = 0;
crap = sizeof(DCBINFO);
rc = DosDevIOCtl(hcom, IOCTL_ASYNC, ASYNC_GETDCBINFO, NULL, 0, &ulParmLen, &dcbinfo, sizeof(DCBINFO), &crap);
fprintf(logfile,"query dcb rc=%d crap=%d\n"
" WriteTimeout %4x\n"
" ReadTimeout %4x\n"
" flags1 %2x flags2 %x flags3 %x\n",
rc, crap,
dcbinfo.usWriteTimeout,
dcbinfo.usReadTimeout,
dcbinfo.fbCtlHndShake,
dcbinfo.fbFlowReplace,
dcbinfo.fbTimeout); fflush(stdout);
/* Call Category 1 Function 41H Set Baud Rate */
ulParmLen = 4;
rc = DosDevIOCtl(hcom, IOCTL_ASYNC, ASYNC_SETBAUDRATE, &profile.ComBaud,
sizeof(profile.ComBaud), &ulParmLen, NULL, 0, (PULONG)NULL);
fprintf(logfile,"baud rate set rc=%d\n", rc); fflush(stdout);
/**********************************************************************/
/* Use wait-for-input mode so the COM thread can do blocking reads */
/* against hcom until any data is available. */
/**********************************************************************/
dcbinfo.fbTimeout &= ~(0x06); /* Clear bits, then set */
dcbinfo.fbTimeout |= MODE_WAIT_READ_TIMEOUT;
dcbinfo.usReadTimeout = -1; /* Never! */
/* Call Category 1 Function 53H Set Device Control Block */
ulParmLen = sizeof(DCBINFO);
rc = DosDevIOCtl(hcom, IOCTL_ASYNC, ASYNC_SETDCBINFO, &dcbinfo, sizeof(DCBINFO), &ulParmLen, NULL, 0, (PULONG)NULL);
fprintf(logfile,"set dcb rc = %d unparmlen=%d\n", rc, ulParmLen);
CommSpeak = &TxComOut;
if (profile.DialString[0]) // user specified init string
{
(*CommSpeak)(profile.DialString);
(*CommSpeak)("\015");
}
else // send a default modem init string
(*CommSpeak)("ATE1\015"); // tell modem to echo commands
return 0; // show successful open
}
void main(int argc, char **argv)
{
HMQ hmq; /* message queue handle */
QMSG qmsg; /* message from message queue */
ULONG flCreate; /* window creation control flags*/
SWP swp;
int n;
RECTL rcl;
logfile = fopen(LOG_FILE, "w"); // debug log
scorefile = fopen(SCORE_FILE, "a"); // game score
/*******************/
/* parse arguments */
/*******************/
profile.BoardSize = 1; // small
profile.CommMode = 0; // preset serial port
profile.ComPort = 0; // COM port number (preset search mode)
profile.ComBaud = 9600; // COM port baud rate
profile.WinX = profile.WinY = 0; // show default window dimensions
profile.DialString[0] = 0; // no dialstring by default
profile.wsc = "green";
profile.bsc = "brown";
profile.wpc = "white";
profile.bpc = "black";
profile.fcp = "CMD.EXE";
for (n=1; n<argc; n++)
{
if (*argv[n] != '/') continue;
if (strcmp(argv[n]+1, "wsc") == 0 && ++n < argc)
profile.wsc = argv[n];
else if (strcmp(argv[n]+1, "bsc") == 0 && ++n < argc)
profile.bsc = argv[n];
else if (strcmp(argv[n]+1, "wpc") == 0 && ++n < argc)
profile.wpc = argv[n];
else if (strcmp(argv[n]+1, "bpc") == 0 && ++n < argc)
profile.bpc = argv[n];
else if (strcmp(argv[n]+1, "fcp") == 0 && ++n < argc)
profile.fcp = argv[n];
else switch (argv[n][1])
{
case 'B': case 'b': // board size
sscanf(argv[n]+2, "%d", &profile.BoardSize);
break;
case 'c': case 'C': // COM port number to use
if (sscanf(argv[n]+2, "%d", &profile.ComPort) != 1)
profile.ComPort = 0;
profile.CommMode = 0;
break;
case 'P': case 'p': // COM port parameters /P9600,8,N,1
sscanf(argv[n]+2, "%d", &profile.ComBaud);
break;
case 'S': case 's': // use session instead of comm port
profile.CommMode = 1;
break;
case 'X': case 'x': // X dimension
sscanf(argv[n]+2, "%d", &profile.WinX);
break;
case 'Y': case 'y': // Y dimension
sscanf(argv[n]+2, "%d", &profile.WinY);
break;
case 'D': case 'd': // Dial string for modem
if (argv[n][2] != '"') // simple non-quoted string
strcpy(profile.DialString, argv[n]+2);
else
{
char *delim;
strcpy(profile.DialString, argv[n]+3);
while (++n < argc)
if ((delim = strstr(profile.DialString, "\"")) != NULL)
{
*delim = '\0';
break;
}
else
strcat(profile.DialString, argv[n]);
}
}
}
fprintf(logfile,"dialstring: %s\n", profile.DialString);
if (profile.WinX == 0) // choose default based on board size
{
USHORT sizes[] = {600, 800, 1024};
profile.WinX = sizes[profile.BoardSize-1];
}
if (profile.WinY == 0) // choose default based on board size
{
USHORT sizes[] = {600, 768, 1024};
profile.WinY = sizes[profile.BoardSize-1];
}
FW_X = profile.WinX;
FW_Y = profile.WinY;
setup(profile.BoardSize);
hab = WinInitialize(0);
hmq = WinCreateMsgQueue( hab, 0 );
WinRegisterClass( /* Register window class */
hab, /* Anchor block handle */
(PSZ)WCP_MAIN, /* Window class name */
FrameProc, /* Address of window procedure */
CS_SIZEREDRAW, /* No special Class Style */
0 /* No extra window words */
);
WinRegisterClass( /* Register window class */
hab, /* Anchor block handle */
(PSZ)WCP_BOARD, /* Window class name */
BoardProc, /* Address of window procedure */
0, /* No special Class Style */
0 /* No extra window words */
);
WinRegisterClass( /* Register window class */
hab, /* Anchor block handle */
(PSZ)WCP_MSG, /* Window class name */
TermProc, /* Address of window procedure */
0, /* No special Class Style */
0 /* No extra window words */
);
WinRegisterClass( /* Register window class */
hab, /* Anchor block handle */
(PSZ)WCP_STAT, /* Window class name */
StatProc, /* Address of window procedure */
0, /* No special Class Style */
0 /* No extra window words */
);
/**************/
flCreate = FCF_SYSMENU | FCF_SIZEBORDER | FCF_TITLEBAR | FCF_ICON |
FCF_MINMAX | FCF_TASKLIST | FCF_MENU | FCF_ACCELTABLE;
hFrame = WinCreateStdWindow(
HWND_DESKTOP, /* Desktop window is parent */
WS_VISIBLE, /* Frame Class Style */
&flCreate, /* Frame creation flags */
(PSZ)WCP_MAIN, /* Client window class name */
(PSZ)APP_TITLE, /* 0=Use EXE name as title */
0L, /* No special class style */
NULLHANDLE, /* Resource is in .EXE file */
ID_PMICS, /* Frame window identifier */
&hClient /* Client window handle returned */
);
WinSetWindowPos(hFrame, 0L, 0, 0, FW_X, FW_Y, SWP_SIZE);
WinQueryWindowPos(hFrame, &swp); // how big is it including borders?
WinSetWindowPos(hFrame, 0L,
(SHORT)0, // position
(SHORT)(WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - swp.cy),
0, 0, SWP_MOVE);
WinQueryWindowRect(hClient, &rcl); // how big is the client window?
fprintf(logfile,"client: %d %d %d %d\n", rcl.xLeft, rcl.yBottom,
rcl.xRight, rcl.yTop);
CW_X = rcl.xRight;
CW_Y = rcl.yTop;
/**********/
/* parent was hFrame in other method */
hBoard = WinCreateWindow(hClient,(PSZ)WCP_BOARD, (PSZ)NULL, WS_VISIBLE,
FW_BW_X, FW_BW_Y, BW_X, BW_Y,
NULLHANDLE, HWND_TOP, ID_PMICS_BOARD,NULL, NULL);
if (hBoard == NULLHANDLE)
{
fprintf(logfile, "board window not created: error %x\n",
WinGetLastError(hab)), fclose(logfile); goto quit;
}
hTerm = WinCreateWindow(hClient, (PSZ)WCP_MSG, (PSZ)NULL, WS_VISIBLE,
FW_MW_X, FW_MW_Y, MW_X, MW_Y,
NULLHANDLE, HWND_TOP, ID_PMICS_MSG, NULL, NULL);
if (hTerm == NULLHANDLE)
{
fprintf(logfile, "msg window not created: error %x\n",
WinGetLastError(hab)), fclose(logfile); goto quit;
}
hStat = WinCreateWindow(hClient, (PSZ)WCP_STAT, (PSZ)NULL, WS_VISIBLE,
FW_SW_X, FW_SW_Y, SW_X, SW_Y,
NULLHANDLE, HWND_TOP, ID_PMICS_STAT, NULL, NULL);
if (hStat == NULLHANDLE)
{
fprintf(logfile, "stat window not created: error %x\n",
WinGetLastError(hab)), fclose(logfile); goto quit;}
while ( WinGetMsg( hab, &qmsg, 0, 0, 0 ) != FALSE )
WinDispatchMsg( hab, &qmsg );
quit:
if (hStat != NULLHANDLE) WinDestroyWindow (hStat);
if (hTerm != NULLHANDLE) WinDestroyWindow (hTerm);
if (hBoard != NULLHANDLE) WinDestroyWindow (hBoard);
if (hFrame != NULLHANDLE) WinDestroyWindow (hFrame);
WinDestroyMsgQueue (hmq);
WinTerminate (hab);
fclose(logfile);
fclose(scorefile);
}
#ifdef DEAD_CODE
WinMessageBox(HWND_DESKTOP, hwnd,
(PSZ)"SERVER LOGIN message received",
(PSZ)"Menu item selection",0,
MB_MOVEABLE | MB_YESNOCANCEL | MB_ICONEXCLAMATION | MB_DEFBUTTON2);
FRAMECDATA fcdata = {sizeof(FRAMECDATA),
FCF_TITLEBAR | FCF_SYSMENU | FCF_SIZEBORDER |
FCF_MINMAX | FCF_TASKLIST | FCF_MENU | FCF_ACCELTABLE,
NULLHANDLE, ID_PMICS};
hFrame = WinCreateWindow(HWND_DESKTOP, WC_FRAME, APP_TITLE, WS_VISIBLE,
0,0,FW_X,FW_Y,
NULLHANDLE, HWND_TOP, ID_PMICS, &fcdata, NULL);
if (hFrame == NULLHANDLE)
{
fprintf(logfile, "frame window not created: error %x\n",
WinGetLastError(hab)), fclose(logfile); goto quit;
}
BOOL DrawLine(HPS hps, LONG x1, LONG y1, LONG x2, LONG y2)
{
POINTL ptl;
ptl.x = x1;
ptl.y = y1;
GpiMove(hps, &ptl);
ptl.x = x2;
ptl.y = y2;
return (GpiLine(hps, &ptl) == GPI_OK);
}
/* WinMessageBox(HWND_DESKTOP, hwnd,
(PSZ)"CREATE message received!!!",
(PSZ)"CREATE message",0,
MB_MOVEABLE | MB_YESNOCANCEL | MB_ICONEXCLAMATION | MB_DEFBUTTON2);*/
flCreate = FCF_SYSMENU | FCF_SIZEBORDER | FCF_TITLEBAR |
FCF_MINMAX | FCF_MENU | FCF_TASKLIST ;
hFrame = WinCreateStdWindow(
HWND_DESKTOP, /* Desktop window is parent */
WS_VISIBLE, /* Frame Class Style */
&flCreate, /* Frame creation flags */
WCP_MAIN, /* Client window class name */
"PMICS", /* 0=Use EXE name as title */
0L, /* No special class style */
NULLHANDLE, /* Resource is in .EXE file */
ID_PMICS, /* Frame window identifier */
&hClient /* Client window handle returned */
);
WinSetWindowPos(hFrame, 0L,
(SHORT)20, (SHORT)20, /* offset of lower left */
(SHORT)500, (SHORT)500, /* dimension */
SWP_SIZE | SWP_MOVE);
WinSetFocus(HWND_DESKTOP, hFrame);
WinCreateWindow(WinQueryObjectWindow(hClient),
WC_LISTBOX, "new button", WS_VISIBLE,
0,0, 200,100, HWND_TOP, hFrame, 5000, NULL, NULL);
WinCreateWindow(HWND_DESKTOP, WC_LISTBOX, "new button2", WS_VISIBLE,
0,0,200,100,NULLHANDLE, HWND_TOP, 600, NULL, NULL);
/* WinFillRect (hps, &rcInvalid, color);
for (rank = 0; rank <= 8; rank++)
DrawLine(hps, LBX, LBY+rank*SQUARESIZE,
LBX+8*SQUARESIZE, LBY+rank*SQUARESIZE);
for (file = 0; file <= 8; file++)
DrawLine(hps, LBX+file*SQUARESIZE, LBY,
LBX+file*SQUARESIZE, LBY+8*SQUARESIZE);*/
/* from window scrolling in TermPut
HRGN hrgn;
RECTL lineRect;
currow = (++currow) % maxrow;
p.x = 10;
p.y = (16*(maxrow-currow));
GpiMove(hps, &p);
lineRect.xLeft = p.x;
lineRect.yBottom = p.y;
lineRect.xRight = FW_X;
lineRect.yTop = p.y + 15;
GpiSetBackColor(hps, CLR_DARKGRAY);
GpiSetColor(hps, CLR_PINK);
hrgn = GpiCreateRegion(hps, 1, &lineRect);
GpiPaintRegion(hps, hrgn);*/
#define LAST(n) (charSilo[(siloPos-(n)) & 0xff])
int i,j,k;
charSilo[siloPos++] = CHAR1FROMMP(mp1);
if (LAST(1) == '@' && LAST(2) == '#' && LAST(3) == '@')
{ /* wow, a status message has arrived */
for (i=4; i<256; i++)
if (LAST(i) == '#' && LAST(i-1) == '@' && LAST(i-2) == '#')
break;
if (i == 256) return (MRESULT)FALSE; /* error */
for (k=0,j=i; j>=1; j--,k++)
s[k] = LAST(j);
s[k] = '\0';
s2 = ProcessStatusMsg(s);
WinInvalidateRegion(boardMethod, NULLHANDLE, 0);
}
#endif